# -*- coding: utf-8 -*-
"""
数据传输对象(DTO)定义

提供统一的API响应格式和数据传输结构
"""

from typing import Generic, TypeVar, Optional, List, Dict, Any
from pydantic import BaseModel, Field
from datetime import datetime

T = TypeVar('T')


class BaseDTO(BaseModel):
    """基础DTO类"""
    
    class Config:
        from_attributes = True
        json_encoders = {
            datetime: lambda v: v.isoformat() if v else None
        }


class ResponseDTO(BaseModel, Generic[T]):
    """统一响应格式"""
    
    success: bool = Field(True, description="操作是否成功")
    message: str = Field("操作成功", description="响应消息")
    data: Optional[T] = Field(None, description="响应数据")
    timestamp: datetime = Field(default_factory=datetime.utcnow, description="响应时间")
    
    @classmethod
    def success_response(cls, data: T = None, message: str = "操作成功") -> "ResponseDTO[T]":
        """成功响应"""
        return cls(
            success=True,
            message=message,
            data=data,
            timestamp=datetime.utcnow()
        )
    
    @classmethod
    def error_response(cls, message: str = "操作失败", data: T = None) -> "ResponseDTO[T]":
        """错误响应"""
        return cls(
            success=False,
            message=message,
            data=data,
            timestamp=datetime.utcnow()
        )


class PaginationDTO(BaseModel):
    """分页信息"""
    
    page: int = Field(1, ge=1, description="当前页码")
    page_size: int = Field(20, ge=1, le=100, description="每页数量")
    total: int = Field(0, ge=0, description="总记录数")
    total_pages: int = Field(0, ge=0, description="总页数")
    has_next: bool = Field(False, description="是否有下一页")
    has_prev: bool = Field(False, description="是否有上一页")
    
    @classmethod
    def create(cls, page: int, page_size: int, total: int) -> "PaginationDTO":
        """创建分页信息"""
        total_pages = (total + page_size - 1) // page_size if total > 0 else 0
        return cls(
            page=page,
            page_size=page_size,
            total=total,
            total_pages=total_pages,
            has_next=page < total_pages,
            has_prev=page > 1
        )


class ListResponseDTO(BaseModel, Generic[T]):
    """列表响应格式"""
    
    success: bool = Field(True, description="操作是否成功")
    message: str = Field("获取成功", description="响应消息")
    data: List[T] = Field(default_factory=list, description="数据列表")
    pagination: Optional[PaginationDTO] = Field(None, description="分页信息")
    timestamp: datetime = Field(default_factory=datetime.utcnow, description="响应时间")
    
    @classmethod
    def success_response(
        cls, 
        data: List[T], 
        pagination: Optional[PaginationDTO] = None,
        message: str = "获取成功"
    ) -> "ListResponseDTO[T]":
        """成功响应"""
        return cls(
            success=True,
            message=message,
            data=data,
            pagination=pagination,
            timestamp=datetime.utcnow()
        )


class ErrorDetailDTO(BaseModel):
    """错误详情"""
    
    field: str = Field(..., description="错误字段")
    message: str = Field(..., description="错误消息")
    code: Optional[str] = Field(None, description="错误代码")


class ValidationErrorDTO(BaseModel):
    """验证错误响应"""
    
    success: bool = Field(False, description="操作是否成功")
    message: str = Field("数据验证失败", description="响应消息")
    errors: List[ErrorDetailDTO] = Field(..., description="错误详情列表")
    timestamp: datetime = Field(default_factory=datetime.utcnow, description="响应时间")


# === 业务相关DTO ===

class UserDTO(BaseDTO):
    """用户信息DTO"""
    
    id: int
    username: str
    email: str
    full_name: Optional[str] = None
    is_active: bool
    is_superuser: bool
    created_at: datetime
    updated_at: datetime


class UserCreateDTO(BaseModel):
    """用户创建DTO"""
    
    username: str = Field(..., min_length=3, max_length=50, description="用户名")
    email: str = Field(..., description="邮箱")
    password: str = Field(..., min_length=8, description="密码")
    full_name: Optional[str] = Field(None, max_length=100, description="全名")
    is_active: bool = Field(True, description="是否激活")


class UserUpdateDTO(BaseModel):
    """用户更新DTO"""
    
    email: Optional[str] = Field(None, description="邮箱")
    full_name: Optional[str] = Field(None, max_length=100, description="全名")
    is_active: Optional[bool] = Field(None, description="是否激活")


class RoleDTO(BaseDTO):
    """角色信息DTO"""
    
    id: int
    name: str
    description: Optional[str] = None
    is_active: bool
    created_at: datetime
    updated_at: datetime


class PermissionDTO(BaseDTO):
    """权限信息DTO"""
    
    id: int
    name: str
    resource: str
    action: str
    description: Optional[str] = None


class SystemConfigDTO(BaseDTO):
    """系统配置DTO"""
    
    id: int
    config_key: str
    config_value: str
    config_category: str
    config_type: str
    display_name: str
    description: Optional[str] = None
    is_required: bool
    is_readonly: bool
    is_sensitive: bool
    group_name: Optional[str] = None


class SystemConfigCreateDTO(BaseModel):
    """系统配置创建DTO"""
    
    config_key: str = Field(..., description="配置键")
    config_value: str = Field(..., description="配置值")
    config_category: str = Field(..., description="配置分类")
    config_type: str = Field("string", description="配置类型")
    display_name: str = Field(..., description="显示名称")
    description: Optional[str] = Field(None, description="配置描述")
    is_required: bool = Field(False, description="是否必填")
    is_readonly: bool = Field(False, description="是否只读")
    is_sensitive: bool = Field(False, description="是否敏感")
    group_name: Optional[str] = Field(None, description="分组名称")


class SystemConfigUpdateDTO(BaseModel):
    """系统配置更新DTO"""
    
    config_value: str = Field(..., description="配置值")
    change_reason: Optional[str] = Field(None, description="变更原因")


# === 统计相关DTO ===

class StatisticsDTO(BaseModel):
    """统计数据DTO"""
    
    total_users: int = Field(0, description="总用户数")
    active_users: int = Field(0, description="活跃用户数")
    total_customers: int = Field(0, description="总客户数")
    new_customers_today: int = Field(0, description="今日新客户数")
    total_orders: int = Field(0, description="总订单数")
    revenue_today: float = Field(0.0, description="今日收入")


class TrendDataDTO(BaseModel):
    """趋势数据DTO"""
    
    date: str = Field(..., description="日期")
    value: float = Field(..., description="数值")
    label: Optional[str] = Field(None, description="标签")


class ChartDataDTO(BaseModel):
    """图表数据DTO"""
    
    title: str = Field(..., description="图表标题")
    type: str = Field("line", description="图表类型")
    data: List[TrendDataDTO] = Field(..., description="数据点")
    total: Optional[float] = Field(None, description="总计")


# === 客户相关DTO ===

class CustomerDTO(BaseDTO):
    """客户信息DTO"""
    
    id: int
    name: str
    phone: Optional[str] = None
    email: Optional[str] = None
    gender: Optional[str] = None
    age: Optional[int] = None
    address: Optional[str] = None
    customer_type: str
    source: Optional[str] = None
    status: str
    created_at: datetime
    updated_at: datetime


class CustomerCreateDTO(BaseModel):
    """客户创建DTO"""
    
    name: str = Field(..., min_length=1, max_length=100, description="客户姓名")
    phone: Optional[str] = Field(None, max_length=20, description="联系电话")
    email: Optional[str] = Field(None, description="邮箱地址")
    gender: Optional[str] = Field(None, description="性别")
    age: Optional[int] = Field(None, ge=0, le=150, description="年龄")
    address: Optional[str] = Field(None, max_length=500, description="地址")
    customer_type: str = Field("个人", description="客户类型")
    source: Optional[str] = Field(None, description="客户来源")


class CustomerUpdateDTO(BaseModel):
    """客户更新DTO"""
    
    name: Optional[str] = Field(None, min_length=1, max_length=100, description="客户姓名")
    phone: Optional[str] = Field(None, max_length=20, description="联系电话")
    email: Optional[str] = Field(None, description="邮箱地址")
    gender: Optional[str] = Field(None, description="性别")
    age: Optional[int] = Field(None, ge=0, le=150, description="年龄")
    address: Optional[str] = Field(None, max_length=500, description="地址")
    customer_type: Optional[str] = Field(None, description="客户类型")
    source: Optional[str] = Field(None, description="客户来源")
    status: Optional[str] = Field(None, description="客户状态")


class CustomerSearchDTO(BaseModel):
    """客户搜索DTO"""
    
    keyword: Optional[str] = Field(None, description="搜索关键词")
    customer_type: Optional[str] = Field(None, description="客户类型")
    status: Optional[str] = Field(None, description="客户状态")
    source: Optional[str] = Field(None, description="客户来源")
    min_age: Optional[int] = Field(None, ge=0, description="最小年龄")
    max_age: Optional[int] = Field(None, le=150, description="最大年龄")
    gender: Optional[str] = Field(None, description="性别")
    page: int = Field(1, ge=1, description="页码")
    page_size: int = Field(20, ge=1, le=100, description="每页数量")